import router from '@/router'
import store from '@/store'
import axios from 'axios'
import { Message } from 'element-ui'
import { getToken } from './auth'

// create()创建axios新实例
const request = axios.create({
  // baseURL接口基地址  process.env.VUE_APP_BASE_URL,是环境变量 开发模式的 【 基地址+绝对地址=完整的绝对地址请求用 】
  baseURL: process.env.VUE_APP_BASE_URL,
  // timeout请求超时时间 超过时间如果还没有返回就将接口请求取消掉
  // request = axios+额外的配置(更加强大定制化的axios) 增强版本的axios
  // create方法是可以执行多次的，多个实例对用不同的配置项，应付大型的应用
  timeout: 5000 // request timeout
})

// 请求拦截器 在请求正式发送之前 可以对请求参数进行一些额外配置
// 做了什么？header添加了token
request.interceptors.request.use(
  config => {
    // config 请求配置参数对象，可以在发送请求前操作请求参数
    // 统一的注入token
    // const token = store.state.user.token
    const token = getToken()
    // 判断本地与vuex中是否有token
    if (token) {
      // 有token按照规则进行转换和拼接
      config.headers['Authorization'] = `Bearer ${token}`
    }
    // 必须 return 否则请求将没有参数
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器；返回数据到客户端之前对返回值做一些处理
// 做了什么？token失效时，接口401 退出登陆
// 成功回调和失败回调什么时候执行？ http码判断的200-300成功 走第一个回调 不在这个之间走失败回调
request.interceptors.response.use(
  response => {
    // 必须return 否则拿不到后端的数据
    // 这里axios默认会把后端返回的数据存入一个自己包装的对象里面
    // 放到一个名称为data的属性上，如果你想简化他的作用，就可以直接return xxx.data
    // 保证在组件中拿到的数据和后端返回的数据是一致的
    // return responses 包裹状态
    // return response.data
    // 解决办法： 以后后端返回的判断字段为主，前端进行错误自行抛出
    const { data, message, success } = response.data
    if (success) {
      // 接口成功 -》正常返回数据
      return data
    } else {
      // 先给出一个错误信息提示
      Message.warning(message)
      // 接口失败 -》自行抛出错误
      return Promise.reject(message)
    }
  },
  error => {
    console.dir(error)
    if (error.response.status === 401) {
      // 1. 清空数据
      store.commit('user/removeUserInfo')
      // 2. 跳转登录
      router.push('/login')
    }
    return Promise.reject(error)
  }
)

// 导出的是request实例而不是axios
export default request

// Vue. use  和 component 有啥区别？
// Vue. use注册插件 ，component 注册组件全局组件

